#pragma once

#include "object/worldobject.h"
#include "object/updatefields.h"
#include "motion_generators/motion_master.h"
#include "movement/move_spline_init.h"
#include "movement/move_spline.h"

enum UnitState
{
    // persistent state (applied by aura/etc until expire)
    UNIT_STAT_MELEE_ATTACKING = 0x00000001,                 // unit is melee attacking someone Unit::Attack
    UNIT_STAT_ATTACK_PLAYER = 0x00000002,                 // unit attack player or player's controlled unit and have contested pvpv timer setup, until timer expire, combat end and etc
    UNIT_STAT_DIED = 0x00000004,                 // Unit::SetFeignDeath
    UNIT_STAT_STUNNED = 0x00000008,                 // Aura::HandleAuraModStun
    UNIT_STAT_ROOT = 0x00000010,                 // Aura::HandleAuraModRoot
    UNIT_STAT_ISOLATED = 0x00000020,                 // area auras do not affect other players, Aura::HandleAuraModSchoolImmunity
    UNIT_STAT_CONTROLLED = 0x00000040,                 // Aura::HandleAuraModPossess

    // persistent movement generator state (all time while movement generator applied to unit (independent from top state of movegen)
    UNIT_STAT_TAXI_FLIGHT = 0x00000080,                 // player is in flight mode (in fact interrupted at far teleport until next map telport landing)
    UNIT_STAT_DISTRACTED = 0x00000100,                 // DistractedMovementGenerator active

    // persistent movement generator state with non-persistent mirror states for stop support
    // (can be removed temporary by stop command or another movement generator apply)
    // not use _MOVE versions for generic movegen state, it can be removed temporary for unit stop and etc
    UNIT_STAT_CONFUSED = 0x00000200,                 // ConfusedMovementGenerator active/onstack
    UNIT_STAT_CONFUSED_MOVE = 0x00000400,
    UNIT_STAT_ROAMING = 0x00000800,                 // RandomMovementGenerator/PointMovementGenerator/WaypointMovementGenerator active (now always set)
    UNIT_STAT_ROAMING_MOVE = 0x00001000,
    UNIT_STAT_CHASE = 0x00002000,                 // ChaseMovementGenerator active
    UNIT_STAT_CHASE_MOVE = 0x00004000,
    UNIT_STAT_FOLLOW = 0x00008000,                 // FollowMovementGenerator active
    UNIT_STAT_FOLLOW_MOVE = 0x00010000,
    UNIT_STAT_FLEEING = 0x00020000,                 // FleeMovementGenerator/TimedFleeingMovementGenerator active/onstack
    UNIT_STAT_FLEEING_MOVE = 0x00040000,
    // More room for other MMGens

    // High-Level states (usually only with Creatures)
    UNIT_STAT_NO_COMBAT_MOVEMENT = 0x01000000,           // Combat Movement for MoveChase stopped
    UNIT_STAT_RUNNING = 0x02000000,           // SetRun for waypoints and such
    UNIT_STAT_WAYPOINT_PAUSED = 0x04000000,           // Waypoint-Movement paused genericly (ie by script)

    UNIT_STAT_IGNORE_PATHFINDING = 0x10000000,           // do not use pathfinding in any MovementGenerator

    // masks (only for check)

    // can't move currently
    UNIT_STAT_CAN_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED,

    // stay by different reasons
    UNIT_STAT_NOT_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED |
    UNIT_STAT_DISTRACTED,

    // stay or scripted movement for effect( = in player case you can't move by client command)
    UNIT_STAT_NO_FREE_MOVE = UNIT_STAT_ROOT | UNIT_STAT_STUNNED | UNIT_STAT_DIED |
    UNIT_STAT_TAXI_FLIGHT |
    UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,

    // not react at move in sight or other
    UNIT_STAT_CAN_NOT_REACT = UNIT_STAT_STUNNED | UNIT_STAT_DIED |
    UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING,

    // AI disabled by some reason
    UNIT_STAT_LOST_CONTROL = UNIT_STAT_CONFUSED | UNIT_STAT_FLEEING | UNIT_STAT_CONTROLLED,

    // above 2 state cases
    UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL = UNIT_STAT_CAN_NOT_REACT | UNIT_STAT_LOST_CONTROL,

    // masks (for check or reset)

    // for real move using movegen check and stop (except unstoppable flight)
    UNIT_STAT_MOVING = UNIT_STAT_ROAMING_MOVE | UNIT_STAT_CHASE_MOVE | UNIT_STAT_FOLLOW_MOVE | UNIT_STAT_FLEEING_MOVE,

    UNIT_STAT_RUNNING_STATE = UNIT_STAT_CHASE_MOVE | UNIT_STAT_FLEEING_MOVE | UNIT_STAT_RUNNING,

    UNIT_STAT_ALL_STATE = 0xFFFFFFFF,
    UNIT_STAT_ALL_DYN_STATES = UNIT_STAT_ALL_STATE & ~(UNIT_STAT_NO_COMBAT_MOVEMENT | UNIT_STAT_RUNNING | UNIT_STAT_WAYPOINT_PAUSED | UNIT_STAT_IGNORE_PATHFINDING)
};

enum MovementFlags
{
    // Byte 1 (Resets on Movement Key Press)
    MOVEFLAG_NONE = 0x00000000,
    MOVEFLAG_FORWARD = 0x00000001,
    MOVEFLAG_BACKWARD = 0x00000002,
    MOVEFLAG_STRAFE_LEFT = 0x00000004,
    MOVEFLAG_STRAFE_RIGHT = 0x00000008,
    MOVEFLAG_TURN_LEFT = 0x00000010,
    MOVEFLAG_TURN_RIGHT = 0x00000020,
    MOVEFLAG_PITCH_UP = 0x00000040,
    MOVEFLAG_PITCH_DOWN = 0x00000080,

    // Byte 2 (Resets on Situation Change)
    MOVEFLAG_WALK_MODE = 0x00000100,               // Walking

    MOVEFLAG_LEVITATING = 0x00000400,
    MOVEFLAG_FLYING = 0x00000800,               // [-ZERO] is it really need and correct value
    MOVEFLAG_FALLING = 0x00002000,
    MOVEFLAG_FALLINGFAR = 0x00004000,
    MOVEFLAG_SWIMMING = 0x00200000,               // appears with fly flag also
    MOVEFLAG_SPLINE_ENABLED = 0x00400000,
    MOVEFLAG_CAN_FLY = 0x00800000,               // [-ZERO] is it really need and correct value
    MOVEFLAG_FLYING_OLD = 0x01000000,               // [-ZERO] is it really need and correct value

    MOVEFLAG_ONTRANSPORT = 0x02000000,               // Used for flying on some creatures
    MOVEFLAG_SPLINE_ELEVATION = 0x04000000,               // used for flight paths
    MOVEFLAG_ROOT = 0x08000000,               // used for flight paths
    MOVEFLAG_WATERWALKING = 0x10000000,               // prevent unit from falling through water
    MOVEFLAG_SAFE_FALL = 0x20000000,               // active rogue safe fall spell (passive)
    MOVEFLAG_HOVER = 0x40000000
};

// flags that use in movement check for example at spell casting
MovementFlags const movementFlagsMask = MovementFlags(
    MOVEFLAG_FORWARD | MOVEFLAG_BACKWARD | MOVEFLAG_STRAFE_LEFT | MOVEFLAG_STRAFE_RIGHT |
    MOVEFLAG_PITCH_UP | MOVEFLAG_PITCH_DOWN | MOVEFLAG_ROOT |
    MOVEFLAG_FALLING | MOVEFLAG_FALLINGFAR | MOVEFLAG_SPLINE_ELEVATION
);

MovementFlags const movementOrTurningFlagsMask = MovementFlags(
    movementFlagsMask | MOVEFLAG_TURN_LEFT | MOVEFLAG_TURN_RIGHT
);

/**
 * [-ZERO] Need recheck values
 * Value masks for UNIT_FIELD_FLAGS (Taken from source)
 * \todo Document all the flags, not just the ones already commented
 */
enum UnitFlags
{
    UNIT_FLAG_NONE = 0x00000000,
    UNIT_FLAG_UNK_0 = 0x00000001,
    UNIT_FLAG_NON_ATTACKABLE = 0x00000002,           ///< not attackable
    UNIT_FLAG_CLIENT_CONTROL_LOST = 0x00000004,           // Generic unspecified loss of control initiated by server script, movement checks disabled, paired with loss of client control packet.
    UNIT_FLAG_PVP_ATTACKABLE = 0x00000008,           ///< allow apply pvp rules to attackable state in addition to faction dependent state, UNIT_FLAG_UNKNOWN1 in pre-bc mangos
    UNIT_FLAG_RENAME = 0x00000010,           ///< rename creature
    UNIT_FLAG_RESTING = 0x00000020,
    UNIT_FLAG_UNK_6 = 0x00000040,
    UNIT_FLAG_OOC_NOT_ATTACKABLE = 0x00000100,           ///< (OOC Out Of Combat) Can not be attacked when not in combat. Removed if unit for some reason enter combat (flag probably removed for the attacked and it's party/group only) \todo Needs more documentation
    UNIT_FLAG_PASSIVE = 0x00000200,           ///< makes you unable to attack everything. Almost identical to our "civilian"-term. Will ignore it's surroundings and not engage in combat unless "called upon" or engaged by another unit.
    UNIT_FLAG_PVP = 0x00001000,
    UNIT_FLAG_SILENCED = 0x00002000,           ///< silenced, 2.1.1
    UNIT_FLAG_UNK_14 = 0x00004000,           ///< 2.0.8
    UNIT_FLAG_UNK_15 = 0x00008000,           ///< related to jerky movement in water?
    UNIT_FLAG_UNK_16 = 0x00010000,           ///< removes attackable icon
    UNIT_FLAG_PACIFIED = 0x00020000,
    UNIT_FLAG_DISABLE_ROTATE = 0x00040000,
    UNIT_FLAG_IN_COMBAT = 0x00080000,
    UNIT_FLAG_NOT_SELECTABLE = 0x02000000,
    UNIT_FLAG_SKINNABLE = 0x04000000,
    UNIT_FLAG_AURAS_VISIBLE = 0x08000000,           ///< magic detect
    UNIT_FLAG_SHEATHE = 0x40000000,
    // UNIT_FLAG_UNK_31              = 0x80000000           // no affect in 1.12.1

    UNIT_FLAG_NOT_ATTACKABLE_1 = 0x00000080,           ///< ?? (UNIT_FLAG_PVP_ATTACKABLE | UNIT_FLAG_NOT_ATTACKABLE_1) is NON_PVP_ATTACKABLE
    UNIT_FLAG_LOOTING = 0x00000400,           ///< loot animation
    UNIT_FLAG_PET_IN_COMBAT = 0x00000800,           ///< in combat?, 2.0.8
    UNIT_FLAG_STUNNED = 0x00040000,           ///< stunned, 2.1.1
    UNIT_FLAG_TAXI_FLIGHT = 0x00100000,           ///< disable casting at client side spell not allowed by taxi flight (mounted?), probably used with 0x4 flag
    UNIT_FLAG_DISARMED = 0x00200000,           ///< disable melee spells casting..., "Required melee weapon" added to melee spells tooltip.
    UNIT_FLAG_CONFUSED = 0x00400000,
    UNIT_FLAG_FLEEING = 0x00800000,
    UNIT_FLAG_POSSESSED = 0x01000000,           ///< used in spell Eyes of the Beast for pet... let attack by controlled creature |// Unit is under remote control by another unit, movement checks disabled, paired with loss of client control packet. New master is allowed to use melee attack and can't select this unit via mouse in the world (as if it was own character).
    UNIT_FLAG_UNK_28 = 0x10000000,
    UNIT_FLAG_UNK_29 = 0x20000000            ///< used in Feign Death spell
};

#define BASE_MELEERANGE_OFFSET 1.33f
#define BASE_MINDAMAGE 1.0f
#define BASE_MAXDAMAGE 2.0f
#define BASE_ATTACK_TIME 2000

enum UnitMods
{
    UNIT_MOD_STAT_STRENGTH,                                 // UNIT_MOD_STAT_STRENGTH..UNIT_MOD_STAT_SPIRIT must be in existing order, it's accessed by index values of Stats enum.
    UNIT_MOD_STAT_AGILITY,
    UNIT_MOD_STAT_STAMINA,
    UNIT_MOD_STAT_INTELLECT,
    UNIT_MOD_STAT_SPIRIT,
    UNIT_MOD_HEALTH,
    UNIT_MOD_MANA,                                          // UNIT_MOD_MANA..UNIT_MOD_HAPPINESS must be in existing order, it's accessed by index values of Powers enum.
    UNIT_MOD_RAGE,
    UNIT_MOD_FOCUS,
    UNIT_MOD_ENERGY,
    UNIT_MOD_HAPPINESS,
    UNIT_MOD_ARMOR,                                         // UNIT_MOD_ARMOR..UNIT_MOD_RESISTANCE_ARCANE must be in existing order, it's accessed by index values of SpellSchools enum.
    UNIT_MOD_RESISTANCE_HOLY,
    UNIT_MOD_RESISTANCE_FIRE,
    UNIT_MOD_RESISTANCE_NATURE,
    UNIT_MOD_RESISTANCE_FROST,
    UNIT_MOD_RESISTANCE_SHADOW,
    UNIT_MOD_RESISTANCE_ARCANE,
    UNIT_MOD_ATTACK_POWER,
    UNIT_MOD_ATTACK_POWER_RANGED,
    UNIT_MOD_DAMAGE_MAINHAND,
    UNIT_MOD_DAMAGE_OFFHAND,
    UNIT_MOD_DAMAGE_RANGED,
    UNIT_MOD_END,
    // synonyms
    UNIT_MOD_STAT_START = UNIT_MOD_STAT_STRENGTH,
    UNIT_MOD_STAT_END = UNIT_MOD_STAT_SPIRIT + 1,
    UNIT_MOD_RESISTANCE_START = UNIT_MOD_ARMOR,
    UNIT_MOD_RESISTANCE_END = UNIT_MOD_RESISTANCE_ARCANE + 1,
    UNIT_MOD_POWER_START = UNIT_MOD_MANA,
    UNIT_MOD_POWER_END = UNIT_MOD_HAPPINESS + 1
};

enum UnitModifierType
{
    BASE_VALUE = 0,
    BASE_PCT = 1,
    TOTAL_VALUE = 2,
    TOTAL_PCT = 3,
    MODIFIER_TYPE_END = 4
};

class MovementInfo
{
public:
    MovementInfo() : moveFlags(MOVEFLAG_NONE), time(0),
        t_time(0), s_pitch(0.0f), fallTime(0), u_unk1(0.0f) {
    }

#if 0
    // Read/Write methods
    void Read(ByteBuffer& data);
    void Write(ByteBuffer& data) const;
#endif
    // Movement flags manipulations
    void AddMovementFlag(MovementFlags f) { moveFlags |= f; }
    void RemoveMovementFlag(MovementFlags f) { moveFlags &= ~f; }
    bool HasMovementFlag(MovementFlags f) const { return moveFlags & f; }
    MovementFlags GetMovementFlags() const { return MovementFlags(moveFlags); }
    void SetMovementFlags(MovementFlags f) { moveFlags = f; }

    // Position manipulations
    Position const* GetPos() const { return &pos; }
    void SetTransportData(ObjectGuid guid, float x, float y, float z, float o, unsigned int time)
    {
        t_guid = guid;
        t_pos.x = x;
        t_pos.y = y;
        t_pos.z = z;
        t_pos.o = o;
        t_time = time;
    }
    void ClearTransportData()
    {
        t_guid = ObjectGuid();
        t_pos.x = 0.0f;
        t_pos.y = 0.0f;
        t_pos.z = 0.0f;
        t_pos.o = 0.0f;
        t_time = 0;
    }
    ObjectGuid const& GetTransportGuid() const { return t_guid; }
    Position const* GetTransportPos() const { return &t_pos; }
    unsigned int GetTime() { return time; }
    unsigned int GetTransportTime() const { return t_time; }
    unsigned int GetFallTime() const { return fallTime; }
    void ChangeOrientation(float o) { pos.o = o; }
    void ChangePosition(float x, float y, float z, float o) { pos.x = x; pos.y = y; pos.z = z; pos.o = o; }
    void UpdateTime(unsigned int _time) { time = _time; }

    struct JumpInfo
    {
        JumpInfo() : velocity(0.f), sinAngle(0.f), cosAngle(0.f), xyspeed(0.f) {}
        float   velocity, sinAngle, cosAngle, xyspeed;
    };

    JumpInfo const& GetJumpInfo() const { return jump; }
private:
    // common
    unsigned int   moveFlags;                                 // see enum MovementFlags
    unsigned int   time;
    Position pos;
    // transport
    ObjectGuid t_guid;
    Position t_pos;
    unsigned int   t_time;
    // swimming and unknown
    float    s_pitch;
    // last fall time
    unsigned int   fallTime;
    // jumping
    JumpInfo jump;
    // spline
    float    u_unk1;
};

/**
 * This is what decides how an \ref Aura was removed, the cause of it being removed.
 */
enum AuraRemoveMode
{
    AURA_REMOVE_BY_DEFAULT,
    AURA_REMOVE_BY_STACK,           ///< at replace by similar aura
    AURA_REMOVE_BY_CANCEL,          ///< It was cancelled by the user (needs confirmation)
    AURA_REMOVE_BY_DISPEL,          ///< It was dispelled by ie Remove Magic
    AURA_REMOVE_BY_DEATH,           ///< The \ref Unit died and there for it was removed
    AURA_REMOVE_BY_DELETE,          ///< use for speedup and prevent unexpected effects at player logout/pet unsummon (must be used _only_ after save), delete.
    AURA_REMOVE_BY_SHIELD_BREAK,    ///< when absorb shield is removed by damage
    AURA_REMOVE_BY_EXPIRE,          ///< at duration end
    AURA_REMOVE_BY_TRACKING         ///< aura is removed because of a conflicting tracked aura
};

enum DeathState
{
    ALIVE = 0,     ///< show as alive
    JUST_DIED = 1,     ///< temporary state at die, for creature auto converted to CORPSE, for player at next update call
    CORPSE = 2,     ///< corpse state, for player this also meaning that player not leave corpse
    DEAD = 3,     ///< for creature despawned state (corpse despawned), for player CORPSE/DEAD not clear way switches (FIXME), and use m_deathtimer > 0 check for real corpse state
    JUST_ALIVED = 4      ///< temporary state at resurrection, for creature auto converted to ALIVE, for player at next update call
};

// Power type values defines
enum PowerDefaults
{
    POWER_RAGE_DEFAULT = 1000,
    POWER_FOCUS_DEFAULT = 100,
    POWER_ENERGY_DEFAULT = 100,
    POWER_HAPPINESS_DEFAULT = 1000000,
};

namespace battle::object
{

	class Unit : public battle::object::WorldObject
	{
	public:
		Unit();
		Unit* GetOwner() const { return nullptr; }
		virtual bool CanSwim() const = 0;
		virtual bool CanFly() const = 0;
		void OnRelocated() {};
		void CombatStop() {};
		battle::motion::MotionMaster* GetMotionMaster() { return &i_motionMaster; }
		void StopMoving() {}
		bool hasUnitState(unsigned int f) const { return false; }
#if 1
        ObjectGuid const& GetCharmerOrOwnerGuid() const { return GetObjectGuid(); }
        battle::object::Unit* GetCharmerOrOwner() const { return nullptr; }
#endif
        bool IsLinkingEventTrigger() { return false; }
        unsigned char getRace() const { return 0; }
        void SetCharm(Unit* pet);
        void SetPet(Pet* pet) {};
        void SetCharmGuid(ObjectGuid charm) { SetGuidValue(UNIT_FIELD_CHARM, charm); }
        unsigned char getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); }
        void SetChannelObjectGuid(ObjectGuid targetGuid) { SetGuidValue(UNIT_FIELD_CHANNEL_OBJECT, targetGuid); }
        void SetTargetGuid(ObjectGuid targetGuid) { SetGuidValue(UNIT_FIELD_TARGET, targetGuid); }
        void SetCharmerGuid(ObjectGuid owner) { SetGuidValue(UNIT_FIELD_CHARMEDBY, owner); }
        void SetOwnerGuid(ObjectGuid owner) { SetGuidValue(UNIT_FIELD_SUMMONEDBY, owner); }
        void SetCreatorGuid(ObjectGuid creator) { SetGuidValue(UNIT_FIELD_CREATEDBY, creator); }
        unsigned int GetMaxHealth() const { return GetUint32Value(UNIT_FIELD_MAXHEALTH); }
        unsigned int GetMaxPower(Powers power) const { return GetUint32Value(UNIT_FIELD_MAXPOWER1 + power); }
        unsigned char getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); }
        void RemoveAllAuras(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT) {}
        void ClearInCombat() {};
        Powers GetPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
        unsigned int GetDisplayId() const { return GetUint32Value(UNIT_FIELD_DISPLAYID); }
        void SetNativeDisplayId(unsigned int modelId) { SetUint32Value(UNIT_FIELD_NATIVEDISPLAYID, modelId); }
        unsigned int GetCreateMana() const { return GetUint32Value(UNIT_FIELD_BASE_MANA); }
        unsigned int getLevel() const { return GetUint32Value(UNIT_FIELD_LEVEL); }
        void SetCreateStat(Stats stat, float val) { m_createStats[stat] = val; }
        void SetStat(Stats stat, int val) { SetStatInt32Value(UNIT_FIELD_STAT0 + stat, val); }
        void SetCreateHealth(unsigned int val) { SetUint32Value(UNIT_FIELD_BASE_HEALTH, val); }
        void SetCreateMana(unsigned int val) { SetUint32Value(UNIT_FIELD_BASE_MANA, val); }
        void SetArmor(int val) { SetResistance(SPELL_SCHOOL_NORMAL, val); }
        void SetResistance(SpellSchools school, int val) { SetStatInt32Value(UNIT_FIELD_RESISTANCES + school, val); }
        ShapeshiftForm GetShapeshiftForm() const { return ShapeshiftForm(GetByteValue(UNIT_FIELD_BYTES_1, 2)); }
        void SetAttackTime(WeaponAttackType att, unsigned int val) { SetFloatValue(UNIT_FIELD_BASEATTACKTIME + att, val * m_modAttackSpeedPct[att]); }
        void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value) { m_auraModifiersGroup[unitMod][modifierType] = value; }
        float GetStat(Stats stat) const { return float(GetUint32Value(UNIT_FIELD_STAT0 + stat)); }
        bool IsAlive() const { return (m_deathState == ALIVE); };
        void RemoveAllAurasOnDeath() {}
        void SetCanModifyStats(bool modifyStats) { m_canModifyStats = modifyStats; }
        void SetHealth(unsigned int val) {};
        void SetPower(Powers power, unsigned int val) {};
        void SetDisplayId(unsigned int modelId);
        unsigned int GetCreatePowers(Powers power) const;
        virtual unsigned int GetLevelForTarget(Unit const* /*target*/) const { return getLevel(); }
        unsigned short GetMaxSkillValueForLevel(Unit const* target = NULL) const { return (target ? GetLevelForTarget(target) : getLevel()) * 5; }
        void SetPowerType(Powers new_powertype);
        bool CanUseEquippedWeapon(WeaponAttackType attackType) const
        {
            if (IsInFeralForm())
            {
                return false;
            }

            switch (attackType)
            {
            default:
            case BASE_ATTACK:
                return !HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_DISARMED);
            case OFF_ATTACK:
            case RANGED_ATTACK:
                return true;
            }
        }
        bool IsInFeralForm() const
        {
            ShapeshiftForm form = GetShapeshiftForm();
            return form == FORM_CAT || form == FORM_BEAR || form == FORM_DIREBEAR;
        }
#if 0
        SpellAuraHolderBounds GetSpellAuraHolderBounds(unsigned int spell_id)
        {
            return m_spellAuraHolders.equal_range(spell_id);
        }
#endif
        float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType) const;
    private:
        void UpdateModelData();
    protected:
        // Movement info
        MovementInfo m_movementInfo;
        Movement::MoveSpline* movespline = nullptr;
        DeathState m_deathState = ALIVE; ///< The current state of life/death for this \ref Unit
        float m_createStats[MAX_STATS] = {0.0f};
	private:
		battle::motion::MotionMaster i_motionMaster;
        bool m_canModifyStats = false;
        float m_threatModifier[MAX_SPELL_SCHOOL] = {0.0f};
        float m_modAttackSpeedPct[3] = {0.0f};
#if 0
        std::multimap < unsigned int /*spellId*/, SpellAuraHolder* > m_spellAuraHolders;
#endif
        float m_auraModifiersGroup[UNIT_MOD_END][MODIFIER_TYPE_END];
	};

}
